package com.test.qpbgboot.user.service.impl;

import com.test.qpbgboot.base.enums.GeneralStatusEnum;
import com.test.qpbgboot.base.enums.TransactionTypeEnum;
import com.test.qpbgboot.base.exception.ServiceException;
import com.test.qpbgboot.base.response.ResultStatus;
import com.test.qpbgboot.base.service.PayService;
import com.test.qpbgboot.user.mapper.PersonalAccountLogMapper;
import com.test.qpbgboot.user.mapper.PersonalAccountMapper;
import com.test.qpbgboot.user.pojo.dto.AccountLogQuery;
import com.test.qpbgboot.user.pojo.dto.AccountRechargeParam;
import com.test.qpbgboot.user.pojo.entity.PersonalAccount;
import com.test.qpbgboot.user.pojo.entity.PersonalAccountLog;
import com.test.qpbgboot.user.pojo.vo.PersonalAccountLogVO;
import com.test.qpbgboot.user.pojo.vo.PersonalAccountVO;
import com.test.qpbgboot.user.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class AccountServiceImpl implements AccountService {

    @Autowired
    private PersonalAccountMapper personalAccountMapper;
    @Autowired
    private PersonalAccountLogMapper personalAccountLogMapper;
    @Autowired
    private PayService payService;
    @Value("${platform.account.name}")
    private String platformAccountName;

    @Override
    public List<PersonalAccountLogVO> accountLogSelect(AccountLogQuery accountLogQuery) {
        log.debug("账户记录查询业务，参数:{}", accountLogQuery);
        if (accountLogQuery.getId() == null && accountLogQuery.getUserId() == null
                && accountLogQuery.getPersonalId() == null
                && (accountLogQuery.getOrderNo() == null
                || accountLogQuery.getOrderNo().trim().isEmpty()))
        {
            throw new ServiceException(ResultStatus.INVALID_ID);
        }
        if (accountLogQuery.getStartTime() == null) {
            accountLogQuery.setStartTime(new Date(0));
        }
        if (accountLogQuery.getEndTime() == null) {
            accountLogQuery.setEndTime(new Date());
        }
        List<PersonalAccountLogVO> accountLogList =
                personalAccountLogMapper
                        .selectPersonalAccountLogVObyAccountLogQuery(accountLogQuery);
        log.debug("账户记录查询结果:{}", accountLogList);
        return accountLogList;
    }

    @Override
    public PersonalAccountVO accountSelectByUserId(Long userId) {
        log.debug("账户信息查询业务，参数用户id:{}", userId);
        PersonalAccountVO personalAccount = personalAccountMapper
                .selectPersonalAccountVObyUserId(userId);
        log.debug("账户信息查询结果:{}", personalAccount);
        return personalAccount;
    }

    @Override
    public String accountRecharge(AccountRechargeParam accountRechargeParam) {
        log.debug("账户充值业务，参数:{}", accountRechargeParam);
        PersonalAccountVO personalAccount = personalAccountMapper
                .selectPersonalAccountVObyId(accountRechargeParam.getPersonalId());
        if (personalAccount == null) {
            throw new ServiceException(ResultStatus.INVALID_ID);
        }

        BigDecimal amount = accountRechargeParam.getRechargeAmount();
        PersonalAccountLog accountLog = new PersonalAccountLog();
        accountLog.setPersonalId(accountRechargeParam.getPersonalId());
        accountLog.setOrderNo(PayService.generateOrderNo());
        accountLog.setTransactionType(TransactionTypeEnum.RECHARGE.getValue());
        accountLog.setAmount(amount);
        accountLog.setPoints(amount.multiply(new BigDecimal("100")).longValue());
        accountLog.setTMessage("快玩桌游充值服务");
        personalAccountLogMapper.insert(accountLog);
        String formPayStr = payService.payByAlipay(accountLog,
                "/v1/user-account/recharge/notify", "/pay");
        log.debug("支付宝支付页面:formPayStr={}", formPayStr);
        return formPayStr;
    }

    @Override
    public void accountRechargeNotify(Map<String, String> params) {
        log.debug("账户充值支付宝通知业务:{}", params);

        payService.payNotifyByAlipay(params);

        String tradeNo = params.get("out_trade_no");
        if ("TRADE_SUCCESS".equals(params.get("trade_status"))) {
            PersonalAccountLogVO accountLogVO = personalAccountLogMapper
                    .selectPersonalAccountLogVObyOrderNo(tradeNo);
            if (accountLogVO == null) {
                throw new ServiceException(ResultStatus.INVALID_ID, "找不到该订单号的账户记录");
            }
            if (accountLogVO.getPersonalId() == null) {
                throw new ServiceException(ResultStatus.DIRTY_DATA, "账户记录有误");
            }

            PersonalAccountLog accountLog = new PersonalAccountLog();
            BeanUtils.copyProperties(accountLogVO, accountLog);
            accountLog.setTDate(LocalDate.now());
            accountLog.setTTime(LocalTime.now());
            accountLog.setCounterparty(platformAccountName);
            accountTransactionRecord(accountLog);
        } else {
            personalAccountLogMapper.deleteByOrderNo(tradeNo);
            throw new ServiceException(ResultStatus.TRADE_FAILED);
        }
    }

    @Override
    public void accountTransactionRecord(PersonalAccountLog accountLog) {
        log.debug("个人账户交易记录业务:{}", accountLog);
        if (accountLog == null) {
            throw new ServiceException(ResultStatus.FAILURE, "无数据");
        }

        PersonalAccountVO accountVO = personalAccountMapper
                .selectPersonalAccountVObyId(accountLog.getPersonalId());
        if (accountVO == null || !accountVO.getStatus()
                .equals(GeneralStatusEnum.ENABLE.getValue())) {
            throw new ServiceException(ResultStatus.INVALID_ID, "无效的个人账户id");
        }

        if (accountLog.getId() == null) {
            personalAccountLogMapper.insert(accountLog);
        } else {
            if (accountLog.getOrderNo() != null) {
                PersonalAccountLogVO logVO = personalAccountLogMapper
                        .selectPersonalAccountLogVObyOrderNo(
                                accountLog.getOrderNo());
                if (logVO == null || !Objects.equals(logVO.getId(),
                        accountLog.getId()))
                {
                    throw new ServiceException(ResultStatus.DIRTY_DATA, "个人账户记录有误");
                }
            }
            personalAccountLogMapper.update(accountLog);
        }


        PersonalAccount account = new PersonalAccount();
        BeanUtils.copyProperties(accountVO, account);

        List<String> positiveTypeList = new ArrayList<>();
        positiveTypeList.add(TransactionTypeEnum.RECHARGE.getValue());
        positiveTypeList.add(TransactionTypeEnum.REFUND.getValue());
        positiveTypeList.add(TransactionTypeEnum.TRANSFER_INCOME.getValue());
        List<String> negativeTypeList = new ArrayList<>();
        negativeTypeList.add(TransactionTypeEnum.EXPENDITURE.getValue());
        negativeTypeList.add(TransactionTypeEnum.WITHDRAWAL.getValue());
        negativeTypeList.add(TransactionTypeEnum.TRANSFER_EXPENSES.getValue());

        String type = accountLog.getTransactionType();
        if (positiveTypeList.contains(type)) {
            account.setAccountBalance(account.getAccountBalance()
                    .add(accountLog.getAmount()));
        } else if (negativeTypeList.contains(type)) {
            account.setAccountBalance(account.getAccountBalance()
                    .subtract(accountLog.getAmount()));
        }
        account.setPoints(account.getPoints() + accountLog.getPoints());
        personalAccountMapper.updateByUserId(account);
    }


}
